home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / accounts / acct-1.3 / acct-1 / acct-1.3.73 / utils / lastcomm.c < prev    next >
C/C++ Source or Header  |  1995-07-09  |  8KB  |  308 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *   This product includes software developed by the University of
  16.  *   California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)lastcomm.c   5.11.2 (Berkeley) 7/9/1995";
  42. #endif /* not lint */
  43.  
  44. /*
  45.  * last command
  46.  */
  47. #include <sys/types.h>
  48. #include <sys/param.h>
  49. #include <sys/time.h>
  50. #include <linux/acct.h>
  51. #include <sys/file.h>
  52. #include <sys/stat.h>
  53. #include <utmp.h>
  54. #include <ctype.h>
  55. #include <stdio.h>
  56. #include <string.h>
  57. #include <pwd.h>
  58. #include <getopt.h>
  59. #include <sys/types.h>
  60. #include <unistd.h>
  61. #include "pathnames.h"
  62.  
  63. #define LINESIZE   6
  64. #define _PATH_DEV "/dev/"
  65. #define NODEV (-1)
  66. /*
  67.  * This seems to have to be multiple of struct acct size
  68.  * Now it is 160 * 52
  69.  */
  70. #define DEVSIZE   8320L
  71. #define btodb(x)   ((x)/DEVSIZE)
  72. #define dbtob(x)   ((x)*DEVSIZE)
  73.  
  74. struct acct buf[DEVSIZE / sizeof (struct acct)];
  75.  
  76. time_t expand(unsigned);
  77. char *flagbits(register int);
  78. char *getdev(dev_t);
  79.  
  80. time_t expand (unsigned t)
  81. {
  82.    register time_t nt;
  83.  
  84.    nt = t & 017777;
  85.    t >>= 13;
  86.    while (t) {
  87.       t--;
  88.       nt <<= 3;
  89.    }
  90.    return (nt);
  91. }
  92.  
  93. #define BIT(flag, ch) if (f & flag) *p++ = ch;
  94.  
  95. char *flagbits(register int f)
  96. {
  97.    static char flags[20];
  98.    char *p, *strcpy();
  99.  
  100.    p = strcpy(flags, "-    ");
  101.    BIT(ASU, 'S');
  102.    BIT(AFORK, 'F');
  103.    BIT(ACORE, 'D');
  104.    BIT(AXSIG, 'X');
  105.    return (flags);
  106. }
  107.  
  108. int ok(register char **argv, register struct acct *acp)
  109. {
  110.    register char *cp;
  111.    char *user_from_uid(uid_t, int);
  112.  
  113.    do {
  114.       cp = user_from_uid(acp->ac_uid, 0);
  115.       if (!strcmp(cp, *argv)) 
  116.          return(1);
  117.       if ((cp = getdev(acp->ac_tty)) && !strcmp(cp, *argv))
  118.          return(1);
  119.       if (!strncmp(acp->ac_comm, *argv, sizeof(acp->ac_comm)))
  120.          return(1);
  121.    } while (*++argv);
  122.    return(0);
  123. }
  124.  
  125. #include <sys/dir.h>
  126.  
  127. #define N_DEVS 131      /* hash value for device names */
  128. #define NDEVS 2048      /* max number of file names in /dev */
  129.  
  130. struct   devhash {
  131.    dev_t   dev_dev;
  132.    char   dev_name [LINESIZE + 1];
  133.    struct   devhash * dev_nxt;
  134. };
  135. struct devhash *dev_hash[N_DEVS];
  136. struct devhash *dev_chain;
  137. #define HASH(d) (((int) d) % N_DEVS)
  138.  
  139. void setupdevs()
  140. {
  141.    register DIR * fd;
  142.    register struct devhash * hashtab;
  143.    register ndevs = NDEVS;
  144.    struct direct * dp;
  145.    char *malloc();
  146.  
  147.    /*NOSTRICT*/
  148.    hashtab = (struct devhash *)malloc(NDEVS * sizeof(struct devhash));
  149.    if (hashtab == (struct devhash *)0) {
  150.       fputs("No mem for dev table\n", stderr);
  151.       return;
  152.    }
  153.    if ((fd = opendir(_PATH_DEV)) == NULL) {
  154.       perror(_PATH_DEV);
  155.       return;
  156.    }
  157.    while ((dp = readdir(fd))) {
  158.       if (dp->d_ino == 0)
  159.          continue;
  160.       if (strncmp(dp->d_name, "vc", 2) && strncmp(dp->d_name, "tty", 3) &&
  161.           strcmp(dp->d_name, "console"))
  162.          continue;
  163.       (void)strncpy(hashtab->dev_name, dp->d_name, LINESIZE);
  164.       hashtab->dev_name[LINESIZE] = 0;
  165.       hashtab->dev_nxt = dev_chain;
  166.       dev_chain = hashtab;
  167.       hashtab++;
  168.       if (--ndevs <= 0)
  169.          break;
  170.    }
  171.    closedir(fd);
  172. }
  173.  
  174. char *getdev(dev_t dev)
  175. {
  176.    register struct devhash *hp, *nhp;
  177.    struct stat statb;
  178.    char name[sizeof(hp->dev_name) + 6];
  179.    static dev_t lastdev = (dev_t) -1;
  180.    static char *lastname;
  181.    static int init = 0;
  182.    char *strcpy(), *strcat();
  183.  
  184.    if (dev == (dev_t) NODEV)
  185.       return ("__");
  186.    if (dev == lastdev)
  187.       return (lastname);
  188.    if (!init) {
  189.       setupdevs();
  190.       init++;
  191.    }
  192.    for (hp = dev_hash[HASH(dev)]; hp; hp = hp->dev_nxt)
  193.       if (hp->dev_dev == dev) {
  194.          lastdev = dev;
  195.          return (lastname = hp->dev_name);
  196.       }
  197.    for (hp = dev_chain; hp; hp = nhp) {
  198.       nhp = hp->dev_nxt;
  199.       (void)strcpy(name, _PATH_DEV);
  200.       strcat(name, hp->dev_name);
  201.       if (stat(name, &statb) < 0)   /* name truncated usually */
  202.          continue;
  203.       if ((statb.st_mode & S_IFMT) != S_IFCHR)
  204.          continue;
  205.       hp->dev_dev = statb.st_rdev;
  206.       hp->dev_nxt = dev_hash[HASH(hp->dev_dev)];
  207.       dev_hash[HASH(hp->dev_dev)] = hp;
  208.       if (hp->dev_dev == dev) {
  209.          dev_chain = nhp;
  210.          lastdev = dev;
  211.          return (lastname = hp->dev_name);
  212.       }
  213.    }
  214.    dev_chain = (struct devhash *) 0;
  215.    return ("??");
  216. }
  217.  
  218. char *user_from_uid(uid_t uid, int val)
  219. {
  220.    struct passwd *p;
  221.    
  222.    p=getpwuid(uid);
  223.    if(p!=NULL)
  224.       return(p->pw_name);
  225.    return("???");
  226. }
  227.  
  228. int main(int argc, char **argv)
  229. {
  230.    extern int optind;
  231.    extern char *optarg;
  232.    register struct acct *acp;
  233.    register int cc;
  234.    register long bn;
  235.    struct stat sb;
  236.    int ch, fd;
  237.    long endtime;
  238.    char *acctfile, *user_from_uid(uid_t, int);
  239.    long lseek();
  240.  
  241.    acctfile = _PATH_ACCT;
  242.    while ((ch = getopt(argc, argv, "f:")) != EOF)
  243.       switch((char)ch) {
  244.       case 'f':
  245.          acctfile = optarg;
  246.          break;
  247.       case '?':
  248.       default:
  249.          fputs("lastcomm [ -f file ]\n", stderr);
  250.          exit(1);
  251.       }
  252.    argv += optind;
  253.  
  254.    fd = open(acctfile, O_RDONLY);
  255.    if (fd < 0) {
  256.       perror(acctfile);
  257.       exit(1);
  258.    }
  259.    printf("%-*.*s %s %-*s %-*s %s %-11s %.19s\n",
  260.       (int) sizeof(acp->ac_comm),
  261.       (int) sizeof(acp->ac_comm),
  262.       "Command",
  263.       "Flags",
  264.       UT_NAMESIZE,
  265.       "User",
  266.       LINESIZE,
  267.       "Tty",
  268.       "PagFlt",
  269.       "Time",
  270.       "Endtime");
  271.       
  272.    (void)fstat(fd, &sb);
  273.    for (bn = btodb(sb.st_size); bn >= 0; bn--) {
  274.       (void)lseek(fd, (off_t)dbtob(bn), L_SET);
  275.       cc = read(fd, buf, DEVSIZE);
  276.       if (cc < 0) {
  277.          perror("read");
  278.          break;
  279.       }
  280.       acp = buf + ((cc / sizeof (buf[0])) - 1);
  281.       for (; acp >= buf; acp--) {
  282.          register char *cp;
  283.          time_t x;
  284.  
  285.          if (acp->ac_comm[0] == '\0')
  286.             (void)strcpy(acp->ac_comm, "?");
  287.          for (cp = &acp->ac_comm[0];
  288.               cp < &acp->ac_comm[sizeof(acp->ac_comm)] && *cp;
  289.               cp++)
  290.             if (!isascii(*cp) || iscntrl(*cp))
  291.                *cp = '?';
  292.          if (*argv && ! ok(argv, acp))
  293.             continue;
  294.          x = expand(acp->ac_utime) + expand(acp->ac_stime);
  295.          endtime = acp->ac_btime + acp->ac_etime;
  296.          printf("%-*.*s %s %-*s %-*s %6ld %6.2f secs %.19s\n",
  297.             (int) sizeof(acp->ac_comm),
  298.                  (int) sizeof(acp->ac_comm),
  299.             acp->ac_comm, flagbits(acp->ac_flag),
  300.             UT_NAMESIZE, user_from_uid(acp->ac_uid, 0),
  301.             LINESIZE, getdev(acp->ac_tty),
  302.             acp->ac_minflt + acp->ac_majflt,
  303.             x / (double)AHZ, ctime(&endtime));
  304.       }
  305.    }
  306.    return 0;
  307. }
  308.